home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: MegaDisc / MegaDisc 28 (1992-05)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2).zip / MegaDisc 28 (1992-05)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2).adf / Programming / ILBM_Prog / ILBM_Code / ILBM.c < prev    next >
C/C++ Source or Header  |  1992-05-26  |  16KB  |  470 lines

  1. /************************************************************************
  2.  
  3.    ILBM.c
  4.    Routines for reading IFF_ILBM files.
  5.    28/02/1992 by Ray Markham.
  6.  
  7.    This code is included with the article for using IFF_ILBM files in
  8.    MEGADISC 27.
  9.  
  10.    This code is in the public domain. So you can use it and abuse it to
  11.    your heart's content.
  12.    The code also follows the EA standards for file access.
  13.    This file with ILBM.h compile to ILBM.o for linking with other code.
  14.    
  15.    If you have any questions or you use this code in your own programs
  16.    please send me an example of the executable so I can see how well
  17.    the code is being used. I can be contacted at the following address:-
  18.  
  19.                               Ray Markham
  20.                               P.O. Box 1590
  21.                               Port Macquarie, NSW
  22.                               2444
  23.                               Australia
  24.  
  25. ************************************************************************/
  26.  
  27. #include <exec/types.h>
  28. #include <exec/memory.h>
  29. #include <intuition/intuition.h>
  30. #include <libraries/dos.h>
  31. #include <libraries/dosextens.h>
  32. #include "ILBM.h"
  33.  
  34. extern   struct   FileHandle  *Open();
  35. extern   PLANEPTR AllocRaster();
  36.  
  37.                            /* ILBM.c functions.                         */
  38. VOID  ReadCMAP();          /* Read the colour map into store            */
  39. VOID  ReadABIT();          /* Read an ABIT chunk of ACBM file           */
  40. VOID  ReadBitMAPheader();  /* Self explanitory.                         */
  41. VOID  ReadBODY();          /* To read the BODY chunk.                   */
  42. VOID  DecodeCompr();       /* deal with ByteRun1 compression            */
  43. VOID  PlainRead();         /* body with no compression                  */
  44. VOID  ReadChunk();         /* Speaks for itself. Then decide what else  */
  45. VOID  DumpChunk();         /* Not a useful ILBM/ACBM chunk.             */
  46. VOID  FadeDown();          /* Fade up viewport from black to CMAP1      */
  47. VOID  FadeUp();            /* Fade viewport from CMAP1 to black.        */
  48. VOID  BlackoutVP();        /* make CMAP2 black and load into viewport   */
  49. VOID  PutCMAP();           /* put CMAP1 into viewport.                  */
  50.  
  51. BOOL  ReadFile();          /* Do the file work.                         */
  52. BOOL  MakeBitMap();
  53. BOOL  FreeBitMap();
  54. BOOL  ReadChunkHeader();
  55.  
  56. struct   FormHeader     formheader;    /* this is for the form header   */
  57. struct   ChunkHeader    chunkheader;   /* chunk headers go here         */
  58. struct   BitMapHeader   bmHeader;      /* storage for bit map header    */
  59.  
  60. LONG     bytesread;           /* bytes read from file                */
  61. LONG     totalbytes;          /* total bytes on file                 */
  62. LONG     rLen;                /* bytes read from disc                */
  63.  
  64. USHORT   cmap1[96];           /* colourmap                           */
  65. USHORT   cmap2[96];           /* spare colourmap for fade up/down    */
  66.  
  67. UBYTE    powers_of_two[] = { 2, 4, 8, 16, 32 };
  68.  
  69. /********************************************************************/
  70. /* Here is the ILBM workhorse. The routine to open and start read.  */
  71. /********************************************************************/
  72.  
  73. BOOL  ReadFile(filename,bitmap,viewport,code)
  74.       char *filename;                  /* filename             */
  75.       struct BitMap *bitmap;           /* bitmap to be used    */
  76.       struct ViewPort *viewport;       /* viewport address     */
  77.       UBYTE  code;                     /* colour change flag   */
  78. {
  79.    struct   FileHandle  *fHandle;
  80.    BOOL     success = FALSE;        /* successful open IFF_ILBM   */
  81.    
  82.    fHandle = Open(filename, MODE_OLDFILE);   /* Open the file     */
  83.    if(fHandle)
  84.    {
  85.       success = ReadChunkHeader(fHandle);    /* Check for ILBM or ACBM  */
  86.       if(success);
  87.       {
  88.          while (bytesread<totalbytes)  
  89.             ReadChunk(fHandle,bitmap,viewport,code);
  90.       }
  91.       Close(fHandle);               /* See this one closes what it uses */
  92.    }
  93.    return(success);
  94. }
  95.  
  96. /************************************************************/
  97. /* Read the ChunkhHader. Store the length                   */
  98. /* and check for an ILBM or ACBM file                       */
  99. /************************************************************/
  100.  
  101. BOOL  ReadChunkHeader(fHandle)
  102.    struct   FileHandle  *fHandle;
  103. {
  104.    BOOL  success;
  105.    
  106.    rLen = Read(fHandle,&formheader,sizeof(struct FormHeader));
  107.                                     /* read the header block   */
  108.    bytesread = rLen;
  109.    totalbytes = formheader.Size;    /* file is this big        */
  110.    
  111.    switch(formheader.Type)
  112.    {
  113.    case  ID_ILBM:
  114.       success = TRUE;               /* if ILBM  */
  115.       break;
  116.    case  ID_ACBM:
  117.       success = TRUE;               /* if ACBM  */
  118.       break;
  119.    default:
  120.       success = FALSE;              /* File is not for us.  */
  121.       break;
  122.    }
  123.    return (success);
  124. }
  125.  
  126. /************************************************************************/
  127. /* Routine for reading a ChunkHeader and deciding what to call to read  */
  128. /************************************************************************/
  129.  
  130. VOID  ReadChunk(fHandle,bitmap,viewport,code)
  131.       struct   FileHandle  *fHandle;
  132.       struct   BitMap   *bitmap;
  133.       struct   ViewPort *viewport;
  134.       UBYTE    code;
  135. {
  136.    rLen = Read(fHandle,&chunkheader,sizeof(struct ChunkHeader));
  137.  
  138.    bytesread += sizeof (struct ChunkHeader);
  139.    bytesread += chunkheader.Size;
  140.    
  141.    switch(chunkheader.Header)
  142.    {
  143.    case  ID_BMHD:
  144.       ReadBitMAPheader(fHandle,bitmap,code);
  145.       break;
  146.    case  ID_CMAP: 
  147.       ReadCMAP(fHandle,viewport,code);
  148.       break;
  149.    case  ID_BODY:
  150.       ReadBODY(fHandle,bitmap);
  151.       break;
  152.    case  ID_ABIT:
  153.       ReadBODY(fHandle,bitmap);
  154.       break;
  155.    default:                      /* Not a chunk that we want   */
  156.       DumpChunk(fHandle);        /* so get rid of it...        */
  157.       break;
  158.    }
  159. }
  160.  
  161. /************************************************************************/
  162. /* Routine for reading the Bit Map Header chunk and decoding it.        */
  163. /************************************************************************/
  164.  
  165. VOID  ReadBitMAPheader(fHandle,bitmap,code)
  166.       struct   FileHandle  *fHandle;
  167.       struct   BitMap *bitmap;
  168.       UBYTE    code;
  169. {
  170.    /* just read the bit map header into our BitMapHeader structure   */
  171.    /* and we'll just access it directly from here.                   */
  172.    
  173.    rLen = Read(fHandle,&bmHeader,sizeof(struct BitMapHeader));
  174. }
  175.  
  176. /************************************************************************/
  177. /* this chunk contains the colour information                           */
  178. /************************************************************************/
  179.  
  180. VOID  ReadCMAP(fHandle,viewport,code)
  181.       struct   FileHandle  *fHandle;
  182.       struct   ViewPort *viewport;
  183.       UBYTE    code;
  184. {
  185.    LONG  count;
  186.    char  *tempbuffer;
  187.    
  188.    if(chunkheader.Size & 1)   {  chunkheader.Size++;  }
  189.    tempbuffer=(char *)AllocMem(chunkheader.Size, MEMF_PUBLIC); 
  190.    
  191.    rLen = Read(fHandle,tempbuffer,chunkheader.Size);
  192.    
  193.    switch(code)
  194.    {
  195.    case  NO_USE_CMAP:   /* leave our existing CMAP resident    */
  196.       break;
  197.    case  OK_USE_CMAP:   /* load the pictures CMAP and use it   */
  198.       for (count = 0; count < chunkheader.Size; count++)
  199.       {
  200.          cmap1[count] = ( tempbuffer[count] & 0xff ) >> 4;
  201.          cmap2[count] = 0;
  202.       }
  203.       break;
  204.    default:
  205.       break;
  206.    }
  207.  
  208.    FreeMem(tempbuffer,chunkheader.Size);  /* free buffer */
  209. }
  210. /************************************************************************/
  211. /* the abit chunk of an acbm file can be read straight onto the raster  */
  212. /************************************************************************/
  213.  
  214. VOID  ReadABIT(fHandle,bitmap)
  215.       struct   FileHandle  *fHandle;
  216.       struct   BitMap *bitmap;
  217. {
  218.    USHORT   i;
  219.    SHORT    iHeight;
  220.    
  221.    iHeight = bmHeader.pageHeight;
  222.  
  223.    for (i=0; i < bmHeader.nPlanes; i++)
  224.       rLen = Read(fHandle,bitmap->Planes[i],((bmHeader.width)/8)*bmHeader.pageHeight);
  225. }
  226.  
  227. /************************************************************************/
  228. /* the body chunk of an ilbm file                                       */
  229. /************************************************************************/
  230.  
  231. VOID  ReadBODY(fHandle,bitmap)
  232.       struct   FileHandle  *fHandle;
  233.       struct   BitMap *bitmap;
  234. {
  235.    char  *tempbuffer;
  236.    
  237.    tempbuffer=(char *)AllocMem(chunkheader.Size, MEMF_PUBLIC); 
  238.                                              /* allocate temp buffer    */
  239.    rLen = Read(fHandle,tempbuffer,chunkheader.Size);
  240.                                              /* read data               */
  241.    switch(bmHeader.compression)              /* decompress if required  */
  242.    {
  243.    case  cmpNone:
  244.       PlainRead(tempbuffer, bitmap);         /* no compression          */
  245.       break;
  246.    case  cmpByteRun1:
  247.       DecodeCompr(tempbuffer, bitmap);            /* normal compression      */
  248.       break;
  249.    default:
  250.       printf("Unknown Compression Algorithm  \n");
  251.       break;
  252.    }
  253.    
  254.    FreeMem(tempbuffer,chunkheader.Size);     /* free buffer             */
  255. }
  256.  
  257. /************************************************************************/
  258. /* don't want to use this chunk so I'll just dump it.                   */
  259. /************************************************************************/
  260.  
  261. VOID  DumpChunk(fHandle)
  262.       struct   FileHandle  *fHandle;
  263. {
  264.    char  *tempbuffer;                  /* pointer to temporary storage  */
  265.    
  266.    tempbuffer = (char *)AllocMem(chunkheader.Size, MEMF_PUBLIC); 
  267.                                        /* alloc work buffer             */
  268.    
  269.    rLen = Read(fHandle,tempbuffer,chunkheader.Size);
  270.                                           /* read the chunk into store  */
  271.    FreeMem(tempbuffer,chunkheader.Size);  /* free buffer                */
  272. }
  273.  
  274. /************************************************************************/
  275. /* decode a compressed file                                             */
  276. /* read the next byte inCode                                            */
  277. /* if inCode<128 read the next inCode+1 bytes normally                  */
  278. /* if inCode>128 the next inCode+1 bytes are the same as the next one   */
  279. /************************************************************************/
  280.  
  281. VOID  DecodeCompr(tempbuffer, bitmap)
  282.    char  *tempbuffer;
  283.    struct BitMap *bitmap;
  284. {
  285.    USHORT   rows,planes,columns;
  286.    UBYTE    bCnt,inCode,inByte;
  287.    UBYTE    *place;
  288.    UBYTE    *scrRow;
  289.    SHORT    iHeight;
  290.  
  291.    place = (UBYTE *)tempbuffer;
  292.    
  293.    iHeight = bmHeader.pageHeight;
  294.  
  295.    for (rows=0;rows<iHeight;rows++)
  296.    {
  297.       for (planes=0;planes<bmHeader.nPlanes;planes++)
  298.       {
  299.          scrRow=bitmap->Planes[planes] + (rows*(bmHeader.width)/8);
  300.          bCnt=0;
  301.          while(bCnt<(bmHeader.pageWidth)/8)
  302.          {
  303.             inCode=*(place);
  304.             place++;
  305.             if (inCode<128)
  306.             {
  307.                for(columns=0;columns<inCode+1;columns++) 
  308.                   *(scrRow+bCnt+columns)=*(place++);
  309.                bCnt=bCnt+inCode+1;
  310.             }
  311.             else if (inCode>128)
  312.             {
  313.                inByte= *(place);
  314.                for(columns=0;columns<257-inCode;columns++) 
  315.                   *(scrRow+bCnt+columns)=inByte;
  316.                bCnt=bCnt+257-inCode;
  317.                place++;
  318.             }
  319.          }
  320.       }
  321.    }
  322. }
  323.  
  324. /************************************************************************/
  325. /* no compression, but the bitplanes are interleaved                    */
  326. /************************************************************************/
  327.  
  328. VOID  PlainRead(tempbuffer, bitmap)
  329.       char     *tempbuffer;
  330.       struct   BitMap *bitmap;
  331. {
  332.    SHORT    rows,planes;
  333.    SHORT    iHeight;
  334.    LONG     columns;
  335.    char     *scrRow;
  336.    char     *pointer = tempbuffer;
  337.  
  338.    iHeight = bmHeader.pageHeight;
  339.  
  340.    for (rows=0; rows < iHeight; rows++)
  341.    {
  342.       for (planes=0; planes < bmHeader.nPlanes; planes++)
  343.       {
  344.          scrRow=bitmap->Planes[planes] + rows * (bmHeader.width)/8;
  345.          for (columns=0; columns < (bmHeader.pageWidth)/8; columns++)
  346.          {
  347.             *(scrRow+columns)=*(pointer++);
  348.          }
  349.       }
  350.    }
  351. }
  352.  
  353. /********************************************************************/
  354. /* Routines for allocating and deallocating BitMap storage          */
  355. /********************************************************************/
  356.  
  357. BOOL  MakeBitMap(bitmap, depth, width, height)
  358.    struct   BitMap   *bitmap;
  359.    USHORT   depth, width, height;
  360. {
  361.    USHORT   loop;
  362.    BOOL     success = TRUE;
  363.    
  364.    InitBitMap(bitmap, depth, width, height);
  365.    for(loop = 0; loop<depth; loop++)
  366.    {
  367.       bitmap->Planes[loop] = AllocRaster( width, height );
  368.       if(bitmap->Planes == 0)
  369.       {
  370.          success = FALSE;
  371.       }
  372.    }
  373.    return(success);
  374. }
  375.  
  376. BOOL  FreeBitMap(bitmap)
  377.    struct BitMap *bitmap;
  378. {
  379.    USHORT   i, depth, bytes, rows;
  380.    
  381.    depth =  (bitmap->Depth)&255;
  382.    bytes =  (bitmap->BytesPerRow)&0xffff;
  383.    rows  =  (bitmap->Rows)&0xffff;
  384.    for (i=0;i<depth;i++)
  385.    {
  386.       FreeRaster(bitmap->Planes[i],8*bytes,rows);
  387.    }
  388.    return(0);
  389. }
  390.  
  391. /************************************************************************/
  392. /* these two routines have nothing to do with reading the file but it   */
  393. /* made things easier to have them in the same module as the colourmap  */
  394. /************************************************************************/
  395.  
  396. VOID FadeDown(viewport)         /*slowly decrease each colour intensity*/
  397.    struct ViewPort *viewport;
  398. {
  399.    USHORT   colour_cnt;
  400.    USHORT   cmap_ptr;
  401.    USHORT   nColours;
  402.    USHORT   passes;     /* maximum colour setting is 15  */
  403.    
  404.    nColours = powers_of_two[bmHeader.nPlanes];
  405.    
  406.    for(passes = 0; passes<15; passes++)
  407.    {
  408.       for(colour_cnt = 0, cmap_ptr = 0; colour_cnt <= nColours; colour_cnt++, cmap_ptr+=3)
  409.       {
  410.          if (cmap2[cmap_ptr])     cmap2[cmap_ptr]--;
  411.          if (cmap2[cmap_ptr+1])   cmap2[cmap_ptr+1]--;
  412.          if (cmap2[cmap_ptr+2])   cmap2[cmap_ptr+2]--;
  413.          SetRGB4(viewport, colour_cnt,
  414.                   cmap2[cmap_ptr], cmap2[cmap_ptr+1], cmap2[cmap_ptr+2]);
  415.       }
  416.       Delay(2);
  417.    }
  418. }
  419.  
  420. VOID FadeUp(viewport)             /*slowly increase each colour intensity*/
  421.    struct ViewPort *viewport;
  422. {
  423.    USHORT   colour_cnt;
  424.    USHORT   cmap_ptr;
  425.    USHORT   nColours;
  426.    USHORT   passes;     /* maximum colour setting is 15  */
  427.    
  428.    nColours = powers_of_two[bmHeader.nPlanes];
  429.    
  430.    for(passes = 0; passes<15; passes++)
  431.    {
  432.       for(colour_cnt = 0, cmap_ptr = 0; colour_cnt <= nColours; colour_cnt++, cmap_ptr+=3)
  433.       {
  434.          if (cmap2[cmap_ptr] < cmap1[cmap_ptr])       cmap2[cmap_ptr]++;
  435.          if (cmap2[cmap_ptr+1] < cmap1[cmap_ptr+1])   cmap2[cmap_ptr+1]++;
  436.          if (cmap2[cmap_ptr+2] < cmap1[cmap_ptr+2])   cmap2[cmap_ptr+2]++;
  437.          SetRGB4(viewport, colour_cnt,
  438.                   cmap2[cmap_ptr], cmap2[cmap_ptr+1], cmap2[cmap_ptr+2]);
  439.       }
  440.       Delay(2);
  441.    }
  442. }
  443.  
  444. /************************************************************************/
  445. /* make CMAP2 = black and load to viewport.                             */
  446. /************************************************************************/
  447.  
  448. VOID  BlackoutVP(viewport)
  449.       struct   ViewPort *viewport;
  450. {
  451.    USHORT   count;
  452.    
  453.    for(count = 0; count <= 96; count++)   /* make CMAP2 = black   */
  454.    {
  455.       cmap2[count] = 0;
  456.    }
  457.    
  458.    LoadRGB4(viewport, cmap2, powers_of_two[bmHeader.nPlanes]);
  459. }
  460.  
  461. /************************************************************************/
  462. /* move CMAP1 into viewport.                                            */
  463. /************************************************************************/
  464.  
  465. VOID  PutCMAP(viewport)
  466.       struct   ViewPort *viewport;
  467. {
  468.    LoadRGB4(viewport, cmap1, powers_of_two[bmHeader.nPlanes]);
  469. }
  470.